<template>
    <div style="position: relative">
        <div
            v-if="type === '2'"
            :style="{ height: parseInt(setSize.imgHeight) + vSpace + 'px' }"
            class="verify-img-out"
        >
            <div :style="{ width: setSize.imgWidth, height: setSize.imgHeight }" class="verify-img-panel">
                <img
                    :src="'data:image/png;base64,' + backImgBase"
                    alt=""
                    style="display: block; width: 100%; height: 100%"
                />
                <div v-show="showRefresh" class="verify-refresh" @click="refresh">
                    <i class="iconfont icon-refresh"></i>
                </div>
                <transition name="tips">
          <span v-if="tipWords" :class="passFlag ? 'suc-bg' : 'err-bg'" class="verify-tips">
            {{ tipWords }}
          </span>
                </transition>
            </div>
        </div>
        <!-- 公共部分 -->
        <div
            :style="{ width: setSize.imgWidth, height: barSize.height, 'line-height': barSize.height }"
            class="verify-bar-area"
        >
            <span class="verify-msg" v-text="text"></span>
            <div
                :style="{
          width: leftBarWidth !== undefined ? leftBarWidth : barSize.height,
          height: barSize.height,
          'border-color': leftBarBorderColor,
          transaction: transitionWidth
        }"
                class="verify-left-bar"
            >
                <span class="verify-msg" v-text="finishText"></span>
                <div
                    :style="{
            width: barSize.height,
            height: barSize.height,
            'background-color': moveBlockBackgroundColor,
            left: moveBlockLeft,
            transition: transitionLeft
          }"
                    class="verify-move-block"
                    @mousedown="start"
                    @touchstart="start"
                >
                    <i :class="['verify-icon iconfont', iconClass]" :style="{ color: iconColor }"></i>
                    <div
                        v-if="type === '2'"
                        :style="{
              width: Math.floor((parseInt(setSize.imgWidth) * 47) / 310) + 'px',
              height: setSize.imgHeight,
              top: '-' + (parseInt(setSize.imgHeight) + vSpace) + 'px',
              'background-size': setSize.imgWidth + ' ' + setSize.imgHeight
            }"
                        class="verify-sub-block"
                    >
                        <img
                            :src="'data:image/png;base64,' + blockBackImgBase"
                            alt=""
                            style="display: block; width: 100%; height: 100%; -webkit-user-drag: none"
                        />
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>
<script setup type="text/babel">
/**
 * VerifySlide
 * @description 滑块
 * */
import {aesEncrypt} from './../utils/ase'
import {resetSize} from './../utils/util'
import {getCode, reqCheck} from '@/api/login'

const props = defineProps({
    captchaType: {
        type: String
    },
    type: {
        type: String,
        default: '1'
    },
    //弹出式pop，固定fixed
    mode: {
        type: String,
        default: 'fixed'
    },
    vSpace: {
        type: Number,
        default: 5
    },
    explain: {
        type: String,
        default: ''
    },
    imgSize: {
        type: Object,
        default() {
            return {
                width: '310px',
                height: '155px'
            }
        }
    },
    blockSize: {
        type: Object,
        default() {
            return {
                width: '50px',
                height: '50px'
            }
        }
    },
    barSize: {
        type: Object,
        default() {
            return {
                width: '310px',
                height: '30px'
            }
        }
    }
})

const {t} = useI18n()
const {mode, captchaType, type, blockSize, explain} = toRefs(props)
const {proxy} = getCurrentInstance()
let secretKey = ref(''), //后端返回的ase加密秘钥
    passFlag = ref(''), //是否通过的标识
    backImgBase = ref(''), //验证码背景图片
    blockBackImgBase = ref(''), //验证滑块的背景图片
    backToken = ref(''), //后端返回的唯一token值
    startMoveTime = ref(''), //移动开始的时间
    endMoveTime = ref(''), //移动结束的时间
    tipWords = ref(''),
    text = ref(''),
    finishText = ref(''),
    setSize = reactive({
        imgHeight: 0,
        imgWidth: 0,
        barHeight: 0,
        barWidth: 0
    }),
    moveBlockLeft = ref(undefined),
    leftBarWidth = ref(undefined),
    // 移动中样式
    moveBlockBackgroundColor = ref(undefined),
    leftBarBorderColor = ref('#ddd'),
    iconColor = ref(undefined),
    iconClass = ref('icon-right'),
    status = ref(false), //鼠标状态
    isEnd = ref(false), //是够验证完成
    showRefresh = ref(true),
    transitionLeft = ref(''),
    transitionWidth = ref(''),
    startLeft = ref(0)

const barArea = computed(() => {
    return proxy.$el.querySelector('.verify-bar-area')
})
const init = () => {
    if (explain.value === '') {
        text.value = t('captcha.slide')
    } else {
        text.value = explain.value
    }
    getPictrue()
    nextTick(() => {
        let {imgHeight, imgWidth, barHeight, barWidth} = resetSize(proxy)
        setSize.imgHeight = imgHeight
        setSize.imgWidth = imgWidth
        setSize.barHeight = barHeight
        setSize.barWidth = barWidth
        proxy.$parent.$emit('ready', proxy)
    })

    window.removeEventListener('touchmove', function (e) {
        move(e)
    })
    window.removeEventListener('mousemove', function (e) {
        move(e)
    })

    //鼠标松开
    window.removeEventListener('touchend', function () {
        end()
    })
    window.removeEventListener('mouseup', function () {
        end()
    })

    window.addEventListener('touchmove', function (e) {
        move(e)
    })
    window.addEventListener('mousemove', function (e) {
        move(e)
    })

    //鼠标松开
    window.addEventListener('touchend', function () {
        end()
    })
    window.addEventListener('mouseup', function () {
        end()
    })
}
watch(type, () => {
    init()
})
onMounted(() => {
    // 禁止拖拽
    init()
    proxy.$el.onselectstart = function () {
        return false
    }
})
//鼠标按下
const start = (e) => {
    e = e || window.event
    if (!e.touches) {
        //兼容PC端
        var x = e.clientX
    } else {
        //兼容移动端
        var x = e.touches[0].pageX
    }
    startLeft.value = Math.floor(x - barArea.value.getBoundingClientRect().left)
    startMoveTime.value = +new Date() //开始滑动的时间
    if (isEnd.value == false) {
        text.value = ''
        moveBlockBackgroundColor.value = '#337ab7'
        leftBarBorderColor.value = '#337AB7'
        iconColor.value = '#fff'
        e.stopPropagation()
        status.value = true
    }
}
//鼠标移动
const move = (e) => {
    e = e || window.event
    if (status.value && isEnd.value == false) {
        if (!e.touches) {
            //兼容PC端
            var x = e.clientX
        } else {
            //兼容移动端
            var x = e.touches[0].pageX
        }
        var bar_area_left = barArea.value.getBoundingClientRect().left
        var move_block_left = x - bar_area_left //小方块相对于父元素的left值
        if (
            move_block_left >=
            barArea.value.offsetWidth - parseInt(parseInt(blockSize.value.width) / 2) - 2
        ) {
            move_block_left =
                barArea.value.offsetWidth - parseInt(parseInt(blockSize.value.width) / 2) - 2
        }
        if (move_block_left <= 0) {
            move_block_left = parseInt(parseInt(blockSize.value.width) / 2)
        }
        //拖动后小方块的left值
        moveBlockLeft.value = move_block_left - startLeft.value + 'px'
        leftBarWidth.value = move_block_left - startLeft.value + 'px'
    }
}

//鼠标松开
const end = () => {
    endMoveTime.value = +new Date()
    //判断是否重合
    if (status.value && isEnd.value == false) {
        var moveLeftDistance = parseInt((moveBlockLeft.value || '0').replace('px', ''))
        moveLeftDistance = (moveLeftDistance * 310) / parseInt(setSize.imgWidth)
        let data = {
            captchaType: captchaType.value,
            pointJson: secretKey.value
                ? aesEncrypt(JSON.stringify({x: moveLeftDistance, y: 5.0}), secretKey.value)
                : JSON.stringify({x: moveLeftDistance, y: 5.0}),
            token: backToken.value
        }
        reqCheck(data).then((res) => {
            if (res.repCode == '0000') {
                moveBlockBackgroundColor.value = '#5cb85c'
                leftBarBorderColor.value = '#5cb85c'
                iconColor.value = '#fff'
                iconClass.value = 'icon-check'
                showRefresh.value = false
                isEnd.value = true
                if (mode.value == 'pop') {
                    setTimeout(() => {
                        proxy.$parent.clickShow = false
                        refresh()
                    }, 1500)
                }
                passFlag.value = true
                tipWords.value = `${((endMoveTime.value - startMoveTime.value) / 1000).toFixed(2)}s
            ${t('captcha.success')}`
                var captchaVerification = secretKey.value
                    ? aesEncrypt(
                        backToken.value + '---' + JSON.stringify({x: moveLeftDistance, y: 5.0}),
                        secretKey.value
                    )
                    : backToken.value + '---' + JSON.stringify({x: moveLeftDistance, y: 5.0})
                setTimeout(() => {
                    tipWords.value = ''
                    proxy.$parent.closeBox()
                    proxy.$parent.$emit('success', {captchaVerification})
                }, 1000)
            } else {
                moveBlockBackgroundColor.value = '#d9534f'
                leftBarBorderColor.value = '#d9534f'
                iconColor.value = '#fff'
                iconClass.value = 'icon-close'
                passFlag.value = false
                setTimeout(function () {
                    refresh()
                }, 1000)
                proxy.$parent.$emit('error', proxy)
                tipWords.value = t('captcha.fail')
                setTimeout(() => {
                    tipWords.value = ''
                }, 1000)
            }
        })
        status.value = false
    }
}

const refresh = async () => {
    showRefresh.value = true
    finishText.value = ''

    transitionLeft.value = 'left .3s'
    moveBlockLeft.value = 0

    leftBarWidth.value = undefined
    transitionWidth.value = 'width .3s'

    leftBarBorderColor.value = '#ddd'
    moveBlockBackgroundColor.value = '#fff'
    iconColor.value = '#000'
    iconClass.value = 'icon-right'
    isEnd.value = false

    await getPictrue()
    setTimeout(() => {
        transitionWidth.value = ''
        transitionLeft.value = ''
        text.value = explain.value
    }, 300)
}

// 请求背景图片和验证图片
const getPictrue = async () => {
    let data = {
        captchaType: captchaType.value
    }
    const res = await getCode(data)
    if (res.repCode == '0000') {
        backImgBase.value = res.repData.originalImageBase64
        blockBackImgBase.value = res.repData.jigsawImageBase64
        backToken.value = res.repData.token
        secretKey.value = res.repData.secretKey
    } else {
        tipWords.value = res.repMsg
    }
}
</script>
